package Controllers;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import Boundry.ExecutionDonePanel;
import Boundry.ExecutionPanel;
import Boundry.ExecutionSetTime;
import Boundry.GenericTools.GenericTabel;
import Controllers.GenericToolsForController.BaseClass;
import Controllers.GenericToolsForController.RequestMainStatusEnum;
import Controllers.GenericToolsForController.RequestStepStatusEnum;
import Entity.Request;
import Entity.RequestArray;
import Entity.Status;
import Entity.Worker;
import Exception.ICMException;
/**
 * 
 * @author G16
 *
 */
public class ExecutionLeaderController extends BaseClass 
{
	/*
	 * Singleton 
	 */
	private static  ExecutionLeaderController Instance = null;
	private RequestArray requestsToExecute;
	private RequestArray requestsToSetTime;
	
	private ExecutionPanel myExecutionPanel;
	private ExecutionDonePanel myExecutionDonePanel;
	private ExecutionSetTime setTimeForExecution;

	private String[] fieldsInTable;
	private String[][] strMtrxRequestsToExecute;
	private String[][] strMtrxRequestsToSetTime;
	private int startingIndex ;
	private int[] numberOfTupples;
	private static final int NUMOFTABS = 2;
	private boolean sendMailOn = true;
	private Request currentRequest;
	private Worker exeLdr;
	private int dataEnteredCounter;
	
	
	
	private ExecutionLeaderController(){}
	/**
	 * singlton method get instance
	 * @return
	 */
	public static ExecutionLeaderController getInstance()
	{
		if(Instance == null)
		{
			Instance = new ExecutionLeaderController();
		}
		return Instance;
	}
	/**
	 * init task
	 */
	private void init() 
	{
		fieldsInTable = RequestArray.getEvaluationCommonFields();
		numberOfTupples = new int[NUMOFTABS];
		this.requestsToExecute = new RequestArray();
		this.requestsToSetTime = new RequestArray();
		strMtrxRequestsToExecute =  null;
		strMtrxRequestsToSetTime=  null;
		System.out.println("exe finished init");
	}
	/**
	 * execute stage  - This is the main and most important flow of the execution stage (stage 4). 
	 * This flow includes setting the setting up the gui, checking all the consitions for moving to next stage and updating the state of the system to reflect the 
	 * change.
	 */
	public void execute()
	{
		startingIndex=0;
		this.init();
		exeLdr =  GlobalData.worker;
		buildAllRequestsLists() ;
	}
	
/**
 *  
 *  setter for tupple size. We use this to show the number of requests in each tab in the title of the tab.
 *  This will allow the user to focus on where he most work to do.
 * @param myExecutionPanel2
 */
	private void setTuppleSizesForPanel(ExecutionPanel myExecutionPanel2) {
		for (int i=0 ; i< this.NUMOFTABS ; i++ )
		{
			myExecutionPanel2.setNumberOfTupples(i, numberOfTupples[i]);		
		}
		
	}
	/**
	 * build request list - We use a swing worker thread to keep the load of the Main thread and the gui thread. this will enable us to give a quick smoth responsive feeling
	 * to our user interface. 
	 * Accessing the DB is used here by all standart ocsf protocol we used all along this project.
	 */
	public void buildAllRequestsLists() {
	
		requestsToExecute.clear();
		requestsToSetTime.clear();
		System.out.println(exeLdr.getId());

		
			SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
				@Override
				 public Void doInBackground() 
				 {
					requestsToExecute = new RequestArray(RequestManager.getInstance().getAllRequestsReadyForExecution(exeLdr));
				    requestsToSetTime =  new RequestArray(RequestManager.getInstance().getAllRequestsForExecutionWithoutTime(exeLdr));
					return null;

				}
				@Override
				public void done() 
				{
						System.out.println("Thread worker started building exe");
						try {
							myExecutionPanel = new ExecutionPanel();
							
						} catch (Exception e) {
							e.printStackTrace();
						}
						createDataForPanel();
						setTuppleSizesForPanel(myExecutionPanel);
						myExecutionPanel.setWhatTobuild();
						myExecutionPanel.setStartingIndex(startingIndex);
						myExecutionPanel.buildPanel();
						enterDataToPanel(myExecutionPanel);
						setListenerToViewDataPanel(myExecutionPanel);
						 for (int i =0 ; i< NUMOFTABS ; i++)
				            {
				            	if (myExecutionPanel.getTobuild(i) == true)
				            	{
				            		GlobalData.guiMangaer.switchScreen(myExecutionPanel);
									System.out.println("Thread worker has finished building exe");	
									return;
				            }
				            }
						JOptionPane.showMessageDialog(new JFrame(),"There are no requests in need of Execution", "",JOptionPane.DEFAULT_OPTION);
				            	
				}	
			    };  
			
			worker.execute();
        

         
	}
	
	/**
	 *  enter data panel - This method uses the data i gathered to feed the table  list with request diveded by qulification.
	 * @param myExecutionPanel
	 */
	void enterDataToPanel(ExecutionPanel myExecutionPanel)
	{
	   // build the tables with the matrixes
	
	    if (strMtrxRequestsToExecute != null && myExecutionPanel.getTobuild(0))
	    {
	    	myExecutionPanel.getRequestTableListPanel(0).buildTabel(fieldsInTable, strMtrxRequestsToExecute);
	
	    }
	    if (strMtrxRequestsToSetTime != null && myExecutionPanel.getTobuild(1))
	    {
	    	myExecutionPanel.getRequestTableListPanel(1).buildTabel(fieldsInTable, strMtrxRequestsToSetTime);
	    }
	  
	   
	}
	/**
	 * create data for panel - This method only serves as interrpurter moving us from lists of requests to matrix of String that will be fed to table lists.
	 */
	private void createDataForPanel() 
	{
	//Change all RequestArrays into string matrix	
		strMtrxRequestsToExecute   = requestsToExecute.requestArrayToMatrixEvaluationCommon();
	    strMtrxRequestsToSetTime    =  requestsToSetTime.requestArrayToMatrixEvaluationCommon();
	    //this counter counts lines per table for display options
	    this.numberOfTupples[0] = requestsToExecute.size();
		this.numberOfTupples[1] = requestsToSetTime.size();
        System.out.println(this.numberOfTupples[0]+" " +this.numberOfTupples[1]);

 }
/**
 * execution done proccess
 */
	public void executionDone()
	{
		myExecutionDonePanel = new ExecutionDonePanel();
	    GlobalData.guiMangaer.switchScreen(myExecutionDonePanel);
	    setListenerToInputPanel(myExecutionDonePanel);
	    myExecutionDonePanel.btnAskForMoreTime.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				askForMoreTime(currentRequest);
				
			}
		});
	    myExecutionDonePanel.getBtnExeDone().addActionListener(this);

	}
	/**
	 * finish execution
	 */
	public void finishExecutionDone()
	{
		currentRequest.changeStatus(new Status(RequestStepStatusEnum.EXE_PASSED, RequestMainStatusEnum.OPEN), " Execution is DONE", new Integer(currentRequest.getTimeForTesting())); 
		JOptionPane.showMessageDialog(new JFrame(),"the request will now move to testing phase ", "",JOptionPane.DEFAULT_OPTION);
	}
	
		
	/**
	 * setter execution time	
	 */
public void setExecutionTimeForRequest()
		{	
	        setTimeForExecution = new ExecutionSetTime();
		    GlobalData.guiMangaer.switchScreen(setTimeForExecution);
		    setListenerToInputPanel(setTimeForExecution);
	}
/**
 * finish time setter
 * @param req
 * @throws ICMException
 */
	public void finishSetTime(Request req) throws ICMException 
	{
	    int timeForExecution = (Integer)setTimeForExecution.getComboBox().getSelectedItem();
		req.setTimeForEvaluation(timeForExecution);
		System.out.println("Changing status for request: "+req.getRequestId());
		req.changeStatus(new Status(RequestStepStatusEnum.EXE_UNEXECUTED_WTIH_TIME_PENDING, RequestMainStatusEnum.OPEN), " Execution has set time for stage", timeForExecution); 
		JOptionPane.showMessageDialog(new JFrame(),"Your time request was sent to the inspector for approval ", "",JOptionPane.DEFAULT_OPTION);
		if (sendMailOn )
		{
			if (req.getInspector() == null)
			{
				System.out.println("There is no inspector set, check DB validity!!");
			}
			else
			{
			Notificator.sendEmailNotification(req.getInspector().getEmail(), "Dear Inspector. \n "+
			                                      " new request is pending your approval for estimated time of the Execution stage. Please take the needed steps \n"+
					                              " Thank you, ICM System" );
			}
		}
		GlobalData.request = null;

	}
	
	@Override
	/*
	 * (non-Javadoc)
	 * @see Controllers.GenericToolsForController.BaseClass#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e)
	{
	if (myExecutionPanel != null)
	{
			if (e.getSource() == myExecutionPanel.btnBack) 
			{
				GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);
				return;
			}
           if (e.getSource() == myExecutionPanel.btnRefresh )
			{
        	   startingIndex = myExecutionPanel.getMainTabbedPane().getSelectedIndex();
        	        this.init();
					this.execute();
					return;
				}
           if (e.getSource() == myExecutionPanel.btnNext )
			{
        	   if (myExecutionPanel.getMainTabbedPane().getSelectedComponent() instanceof GenericTabel )
        	   {
        	   GenericTabel currentPanel = (GenericTabel) myExecutionPanel.getMainTabbedPane().getSelectedComponent();
        	   if (currentPanel.isChosen())
        	   {
        		   int intIndexOfChosen = currentPanel.getChosen();
        		   int intChosenTab = -1;
        		   for (int i=0; i< NUMOFTABS ; i++)
        			   {
        			   if (myExecutionPanel.getRequestTableListPanel(i) == currentPanel)
        			   {
        				   intChosenTab = i;
        			   }
        			   }
        		   if (intChosenTab<0) {
        			   System.out.println("Could not find the right panel action performed next button execution leader controller");
        			   return;
        		   }
        		   switch (intChosenTab)
        		   {
        		   case 0:
        			   currentRequest = requestsToExecute.get(intIndexOfChosen);
        			   break;
        		   case 1:
        			   currentRequest = requestsToSetTime.get(intIndexOfChosen);
        			   break;
        		
        			   		
        			 default:
        				 System.out.println("Should not have gotten to here - defualt in switch case in action performed next buttons");
        		   }
        		   System.out.println("You chose request number: "+currentRequest.getRequestId());
    			   if (currentRequest == null)
    			   	{
    				   System.out.println("Waring could not load request to global data at exe leader action preformed");
    				   
    			   }
        		   GlobalData.request = currentRequest;
        		   if (currentRequest!=null &&  currentRequest.isReadyForExecution())
        		   {
        			   executionDone();
        		   }
        		   else
        		   {
        			   if (currentRequest!=null && currentRequest.isExecutionwithoutTime())
        			   {
        				   setExecutionTimeForRequest();
        			   }
        			  
        		   }
        	   }
        	   else
				{
					JOptionPane.showMessageDialog(new JFrame(),
							"To Continue you must Choose Reuquest",
							"Error",
							JOptionPane.ERROR_MESSAGE);
				}
        	   }
				}
		}
	if (myExecutionDonePanel != null)
	{
			if (e.getSource() == myExecutionDonePanel.btnBack) 
			{
			     this.init();
				this.execute();
				return;
			}
			else
				if (e.getSource() == myExecutionDonePanel.btnSubnit)
				{	
						finishExecutionDone();
						GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);
					
				}
				else
					if (e.getSource() == myExecutionDonePanel.getBtnExeDone())
					{	
							finishExecutionDone();
							GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);
						
					}
	}
	if (setTimeForExecution != null) 
	{
		if (e.getSource() == setTimeForExecution.btnBack) 
		{
			GlobalData.guiMangaer.switchScreen(myExecutionPanel);

			return;
		}
		else
			if (e.getSource() == setTimeForExecution.btnSubnit)
			{
						try {
							finishSetTime(currentRequest);
						} catch (ICMException e1) {
							e1.printStackTrace();
						}
					GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);

			}
	}
	
	

}

}
